﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using InterLinq.Client;
using InterLinq.Objects;
using InterLinq.Sebarf;
using InterLinq.Server.Services.Impl;
using InterLinq.Services.Interfaces;
using InterLinq.Test.DH;
using InterLinq.Test.PD;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Sebarf.Client;
using Sebarf.Configuration;
using Sebarf.Core;
using Sebarf.Core.Internal;
using Sebarf.ProcessChains.Interfaces;
using Sebarf.Profiles.WPF;
using Sebarf.Server;
using Sebarf.Services.Impl;
using Sebarf.Services.Interfaces;
using Sebastof.Client.Services.Impl;
using Sebastof.Server.Services.Impl;
using Sebastof.Services.Interfaces;
using Utils;

#endregion

namespace InterLinq.Test {
	/// <summary>
	/// This class tests the change tracking mechanisms of sebastof by using InterLinq.
	/// </summary>
	[TestClass]
	public class TestTracker {
		private static IServer GetServer(int AmountOfProductsToCreate) {
			// create sample data
			Dictionary<Type, IList> data = SampleDataFactory.CreateInterLinqOrdersWithContent(AmountOfProductsToCreate,
																							   AmountOfProductsToCreate);

			// remeber the products on the server
			IQueryable<IProduct> serverProducts = ((List<IProduct>)data[typeof(IProduct)]).AsQueryable();

			// create server query handler
			var queryHandler = new ObjectQueryHandler(new ObjectBasedDataSource(data));

			// create server
			IServer server = WcfBasedServer.Create(delegate {
				// create the base service
				var locator = new ServiceRegistrationLocatorService();
				// register backend locator service
				locator.RegisterService(new BackendProviderService());
				// register query handler locator service
				locator.RegisterService(new QueryHandlerLocatorService { QueryHandler = queryHandler });
				// create engine
				RequestHandlerEngine toReturn = RequestHandlerEngine.Create(locator,
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Application.xaml"),
																			 RequestHandlerLoader
																				.Load(
																				"TestSampleApplication.RequestHandler.Server.Internal.xaml"));
				// add interlinq handler
				locator.GetRegisteredService<IAddRequestHandlerService>().
					AddAddionalHandler(new ExecuteLinqQueryRequestHandler { QueryHandler = queryHandler });
				// set backend provider
				locator.GetRegisteredService<IBackendProviderRegisterService>().
					SetBackendProvider(queryHandler);

				return toReturn;
			});

			return server;
		}

		private static void GetClient(out ServiceRegistrationLocatorService clientServiceLocator, out IClient client,
									   out SampleDataContext ctx) {
			// create base service
			clientServiceLocator = new ServiceRegistrationLocatorService();

			// create engine
			client = WcfBasedClient.Create("Client: " + Guid.NewGuid(),
											RequestHandlerEngine.Create(clientServiceLocator,
																		 RequestHandlerLoader.Load(
																			"TestSampleApplication.RequestHandler.Client.Internal.xaml")));

			//	clientServiceLocator.RegisterService(new ProcessManagerService());
			client.Connect();

			// load profiles
			client.Process(new WpfBasedProfileLoadRequest("Profile", "CacheBasedLazyLoadProfile_Server.xaml"));
			client.ProcessLocal(new WpfBasedProfileLoadRequest("Profile", "CacheBasedLazyLoadProfile.xaml"));

			// populate remote engine
			clientServiceLocator.GetRegisteredService<IRequestRemoteHandlerEngineLocatorService>().SetRemoteEngine(client);

			ctx =
				new SampleDataContext(
					new InterLinqQueryHandler(
						new InterLinqQueryProvider(new SebarfBasedLinqQueryGateway(clientServiceLocator, client))));
			clientServiceLocator.RegisterService(new QueryHandlerLocatorService { QueryHandler = ctx.QueryHandler });

			// ensure dependencies
			client.Process(new ResolveServicesDependenciesRequest());
			client.Process(new ResolveProcessChainDependenciesRequest());
			client.ProcessLocal(new ResolveServicesDependenciesRequest());
			client.ProcessLocal(new ResolveProcessChainDependenciesRequest());

			// startup services
			client.Process(new SetupServicesRequest());
			client.ProcessLocal(new SetupServicesRequest());
		}

		#region Public Methods

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestListIsReplaced() {
			IServer server = GetServer(8);

			try {
				// task container
				var measurements = new PerformanceMeasurements();

				server.Start();

				ServiceRegistrationLocatorService clientServiceLocator1;
				IClient client1;
				SampleDataContext ctx1;
				GetClient(out clientServiceLocator1, out client1, out ctx1);

				IOrder[] results = ctx1.Orders.ToArray();
				IOrder order = results[0];
				Assert.IsTrue(order.OrderPositions is ObservableList<IOrderPosition>);

				//var objTracker = clientServiceLocator1.GetRegisteredService<IObjectTrackerService>() as ObjectTrackerService;

				var positions = order.OrderPositions as ObservableList<IOrderPosition>;
				positions.Add(new InterLinqOrderPosition(10, ctx1.Products.ToArray()[0]) { AttachedServiceLocatorService = clientServiceLocator1 });

				order.OrderPositions[0].Count = 999;

				//order.OrderPositions.RemoveAt(0);
				//Assert.IsTrue(onRemoveAt);

				//order.OrderPositions.Insert(2, new InterLinqOrderPosition(10, dataContext1.Products.ToArray()[0]) { AttachedContext = dataContext1 });
				//Assert.IsTrue(onAddAt);

				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().SubmitChanges();

				IOrder[] results2 = ctx1.Orders.ToArray();
				IOrder order2 = results2[0];
				for (int i = 0; i < order.OrderPositions.Count; i++) {
					Assert.AreEqual(order.OrderPositions[i].Id, order2.OrderPositions[i].Id);
					Assert.AreEqual(order.OrderPositions[i].Count, order2.OrderPositions[i].Count);
				}
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestListIsReplacedLazyLoading() {
			//            // create server
			//            InterLinqServer server = new InterLinqServer();

			//            try {

			//                // task container
			//                PerformanceMeasurements measurements = new PerformanceMeasurements();

			//                // create sample data
			//                server.Start(ServerQueryHandlerFactory.CreateWCFBasedServer(SampleDataFactory.CreateInterLinqOrdersWithContent((int)Math.Pow(2, 3), (int)Math.Pow(2, 4))), ServerProfileFactory.GetAvailableServerProfiles());

			//                // create datacontext
			//                var dataContext1 = ProfileBasedDataContextFactory.CreateDataContext<SampleDataContext>("Client1", ClientQueryHandlerFactory.CreateWCFBasedClient(), ClientProfiles.GetLazyLoadProfile());

			//                var results = dataContext1.Orders.ToArray();
			//                var order = results[0];
			//                bool isEqual = results[0].OrderPositions is ObservableList<IOrderPosition>;
			//                Assert.IsTrue(isEqual);

			//                var objTracker = dataContext1.GetRegisteredService<IObjectTrackerService>() as ObjectTrackerService;
			//                bool onAdd = false;
			//                bool onRemove = false;
			//                bool onChange = false;
			//                bool onAddAt = false;
			//                bool onRemoveAt = false;
			//#if DEBUG
			//                objTracker.Add += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onAdd = true;
			//                });
			//                objTracker.Remove += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onRemove = true;
			//                });
			//                objTracker.Change += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onChange = true;
			//                });
			//                objTracker.Insert += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onAddAt = true;
			//                });
			//                objTracker.RemoveAt += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onRemoveAt = true;
			//                });
			//                var positions = order.OrderPositions as ObservableList<IOrderPosition>;
			//                positions.Add(new InterLinqOrderPosition(10, dataContext1.Products.ToArray()[0]));
			//                Assert.IsTrue(onAdd);

			//                var ordersCheck = dataContext1.Orders.ToArray();

			//                order.OrderPositions.Remove(order.OrderPositions[0]);
			//                Assert.IsTrue(onRemove);

			//                order.OrderPositions[0].Count = 999;
			//                Assert.IsTrue(onChange);

			//                order.OrderPositions.RemoveAt(0);
			//                Assert.IsTrue(onRemoveAt);

			//                order.OrderPositions.Insert(1, new InterLinqOrderPosition(10, dataContext1.Products.ToArray()[0]));
			//                Assert.IsTrue(onAddAt);

			//                dataContext1.SubmitChanges();

			//                var results2 = dataContext1.Orders.ToArray();
			//                var order2 = results2[0];
			//                for (int i = 0; i < order.OrderPositions.Count; i++) {
			//                    Assert.AreEqual<Guid>(order.OrderPositions[i].Id, order2.OrderPositions[i].Id);
			//                    Assert.AreEqual<int>(order.OrderPositions[i].Count, order2.OrderPositions[i].Count);
			//                }
			//#endif
			//            }
			//            catch (Exception ex) {
			//                Logger.WriteError(ex.Message + ex.StackTrace);
			//                Assert.IsTrue(false, ex.Message);

			//            }
			//            finally {

			//                server.Stop();
			//            }
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestReload() {
			IServer server = GetServer(1);

			try {
				// starts the interlinq server
				server.Start();

				// create client

				ServiceRegistrationLocatorService clientServiceLocator1;
				IClient client1;
				SampleDataContext ctx1;
				GetClient(out clientServiceLocator1, out client1, out ctx1);

				ServiceRegistrationLocatorService clientServiceLocator2;
				IClient client2;
				SampleDataContext ctx2;
				GetClient(out clientServiceLocator2, out client2, out ctx2);

				IProduct results1 = ctx1.Products.ToArray()[0];
				IProduct results2 = ctx2.Products.ToArray()[0];

				Assert.IsTrue(results1.Name == results2.Name);

				string testName = Guid.NewGuid().ToString();
				results1.Name = testName;
				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().SubmitChanges();

				Assert.IsFalse(results1.Name == results2.Name);

				clientServiceLocator2.GetRegisteredService<IChangeHandlerService>().Refresh(results2);

				Assert.IsTrue(results1.Name == results2.Name);
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestOTInsert() {
			IServer server = GetServer(1);

			try {
				// starts the interlinq server
				server.Start();

				// create client

				ServiceRegistrationLocatorService clientServiceLocator1;
				IClient client1;
				SampleDataContext ctx1;
				GetClient(out clientServiceLocator1, out client1, out ctx1);

				ServiceRegistrationLocatorService clientServiceLocator2;
				IClient client2;
				SampleDataContext ctx2;
				GetClient(out clientServiceLocator2, out client2, out ctx2);

				IProduct[] results = ctx1.Products.ToArray();
				int OriginalResCount = results.Count();

				var nilp = new InterLinqProduct("TEST", 1);
				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().InsertOnSubmit(nilp);
				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().SubmitChanges();

				IProduct[] results2 = ctx2.Products.ToArray();
				int NewResCount = results2.Count();

				Assert.IsTrue(NewResCount == OriginalResCount + 1);
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestOTInsertOverExistingObject() {
			IServer server = GetServer(1);

			try {
				// starts the interlinq server
				server.Start();

				// create client

				ServiceRegistrationLocatorService clientServiceLocator1;
				IClient client1;
				SampleDataContext ctx1;
				GetClient(out clientServiceLocator1, out client1, out ctx1);

				IOrder results = ctx1.Orders.ToArray()[0];
				int OriginalResCount = results.OrderPositions.Count();
				results.OrderPositions.Add(new InterLinqOrderPosition(99, ctx1.Products.ToArray()[0]));
				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().SubmitChanges();

				ServiceRegistrationLocatorService clientServiceLocator2;
				IClient client2;
				SampleDataContext ctx2;
				GetClient(out clientServiceLocator2, out client2, out ctx2);
				IOrder results2 = ctx2.Orders.ToArray()[0];
				int NewResCount = results2.OrderPositions.Count();

				Assert.IsTrue(NewResCount == OriginalResCount + 1);
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestOTDelete() {
			IServer server = GetServer(1);

			try {
				server.Start();

				ServiceRegistrationLocatorService clientServiceLocator1;
				IClient client1;
				SampleDataContext ctx1;
				GetClient(out clientServiceLocator1, out client1, out ctx1);

				ServiceRegistrationLocatorService clientServiceLocator2;
				IClient client2;
				SampleDataContext ctx2;
				GetClient(out clientServiceLocator2, out client2, out ctx2);

				IProduct[] results = ctx1.Products.ToArray();
				int OriginalResCount = results.Count();

				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().DeleteOnSubmit(
					ctx1.Products.ToArray()[0] as ISebastofApplicationObject);
				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().SubmitChanges();

				IProduct[] results2 = ctx2.Products.ToArray();
				int NewResCount = results2.Count();

				Assert.IsTrue(NewResCount == OriginalResCount - 1);
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Client.Application.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Internal.xaml")]
		[DeploymentItem("TestSampleApplication.RequestHandler.Server.Application.xaml")]
		public void TestOTDeleteOverExistingObject() {
			IServer server = GetServer(1);
			try {
				server.Start();

				ServiceRegistrationLocatorService clientServiceLocator1;
				IClient client1;
				SampleDataContext ctx1;
				GetClient(out clientServiceLocator1, out client1, out ctx1);
				IOrder results = ctx1.Orders.ToArray()[0];
				int OriginalResCount = results.OrderPositions.Count();
				results.OrderPositions.RemoveAt(0);
				clientServiceLocator1.GetRegisteredService<IChangeHandlerService>().SubmitChanges();

				ServiceRegistrationLocatorService clientServiceLocator2;
				IClient client2;
				SampleDataContext ctx2;
				GetClient(out clientServiceLocator2, out client2, out ctx2);
				IOrder results2 = ctx2.Orders.ToArray()[0];
				int NewResCount = results2.OrderPositions.Count();

				Assert.IsTrue(NewResCount == OriginalResCount - 1);
			}
			finally {
				server.Stop();
			}
		}

		[TestMethod]
		//        //[DeploymentItem(@"Profiles\ClientProfiles.xaml")]
		//        //[DeploymentItem(@"Profiles\ServerProfiles.xaml")]
		public void TestListIsReplacedCacheBased() {
			//            // create server
			//            InterLinqServer server = new InterLinqServer();

			//            try {

			//                // task container
			//                PerformanceMeasurements measurements = new PerformanceMeasurements();

			//                // create sample data
			//                server.Start(ServerQueryHandlerFactory.CreateWCFBasedServer(SampleDataFactory.CreateInterLinqOrdersWithContent((int)Math.Pow(2, 3), (int)Math.Pow(2, 4))), ServerProfileFactory.GetAvailableServerProfiles());

			//                // create datacontext
			//                var dataContext1 = ProfileBasedDataContextFactory.CreateDataContext<SampleDataContext>("Client1", ClientQueryHandlerFactory.CreateWCFBasedClient(), ClientProfiles.GetCacheBasedProfile());

			//                var results = dataContext1.Orders.ToArray();
			//                var order = results[0];
			//                bool isEqual = results[0].OrderPositions is ObservableList<IOrderPosition>;
			//                Assert.IsTrue(isEqual);

			//                var objTracker = dataContext1.GetRegisteredService<IObjectTrackerService>() as ObjectTrackerService;
			//                bool onAdd = false;
			//                bool onRemove = false;
			//                bool onChange = false;
			//                bool onAddAt = false;
			//                bool onRemoveAt = false;
			//#if DEBUG
			//                objTracker.Add += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onAdd = true;
			//                });
			//                objTracker.Remove += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onRemove = true;
			//                });
			//                objTracker.Change += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onChange = true;
			//                });
			//                objTracker.Insert += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onAddAt = true;
			//                });
			//                objTracker.RemoveAt += new EventHandler(delegate(Object o, EventArgs e) {
			//                    onRemoveAt = true;
			//                });
			//                var positions = order.OrderPositions as ObservableList<IOrderPosition>;
			//                positions.Add(new InterLinqOrderPosition(10, dataContext1.Products.ToArray()[0]));
			//                Assert.IsTrue(onAdd);

			//                var ordersCheck = dataContext1.Orders.ToArray();

			//                order.OrderPositions.Remove(order.OrderPositions[0]);
			//                Assert.IsTrue(onRemove);

			//                order.OrderPositions[0].Count = 999;
			//                Assert.IsTrue(onChange);

			//                //order.OrderPositions.RemoveAt(0);
			//                //Assert.IsTrue(onRemoveAt);

			//                //order.OrderPositions.Insert(1, new InterLinqOrderPosition(10, dataContext1.Products.ToArray()[0]));
			//                //Assert.IsTrue(onAddAt);

			//                dataContext1.SubmitChanges();

			//                var results2 = dataContext1.Orders.ToArray();
			//                var order2 = results2[0];
			//                for (int i = 0; i < order.OrderPositions.Count; i++) {
			//                    Assert.AreEqual<Guid>(order.OrderPositions[i].Id, order2.OrderPositions[i].Id);
			//                    Assert.AreEqual<int>(order.OrderPositions[i].Count, order2.OrderPositions[i].Count);
			//                }
			//#endif
			//            }
			//            catch (Exception ex) {
			//                Logger.WriteError(ex.Message + ex.StackTrace);
			//                Assert.IsTrue(false, ex.Message);

			//            }
			//            finally {

			//                server.Stop();
			//            }
		}

		#endregion
	}
}